package httpHandler

import (
	"encoding/json"
	baseAuth "gitee.com/zaiqiang231/go-base-app/base_app/auth"
	baseHttp "gitee.com/zaiqiang231/go-base-app/base_app/http"
	sessionHandler "gitee.com/zaiqiang231/go-base-session/app/http/handler"
	sessionProto "gitee.com/zaiqiang231/go-base-session/app/rpc/proto"
	smsProto "gitee.com/zaiqiang231/go-base-sms/app/rpc/proto"
	errCode "gitee.com/zaiqiang231/zcamp-service-user/app/constants"
	"gitee.com/zaiqiang231/zcamp-service-user/app/http/service"
	"gitee.com/zaiqiang231/zcamp-service-user/app/model/req"
	remoteRpc "gitee.com/zaiqiang231/zcamp-service-user/app/rpc/remote"
	"gitee.com/zaiqiang231/zcamp-service-user/app/store"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"net/http"
	"reflect"
)

func CreateUser(c *gin.Context) {
	var request req.UserCreateReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	if len(request.ReqPassword) > 0 {
		password, err := baseAuth.Encrypt(request.ReqPassword)
		if err != nil {
			baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
			return
		}
		request.Password = password
	}

	result, tmperr := json.Marshal(request.ReqImages)
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}
	request.HeaderImg = string(result)

	err := service.ServiceUserInstance.UserCreate(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func UpdateUser(c *gin.Context) {
	var target map[string]interface{}
	if err := c.ShouldBindBodyWith(&target, binding.JSON); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	if _, existed := target["req_password"]; existed {
		if len(target["req_password"].(string)) > 0 {
			password, err := baseAuth.Encrypt(target["req_password"].(string))
			if err != nil {
				baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
				return
			}
			target["password"] = password
		}
	}

	result, tmperr := json.Marshal(target["req_images"])
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}
	target["header_img"] = string(result)

	var request req.UserUpdateReq
	elem := reflect.TypeOf(&request).Elem() //通过反射获取type定义
	for i := 0; i < elem.NumField(); i++ {
		if elem.Field(i).Tag.Get("gorm") == "-" && len(elem.Field(i).Tag.Get("json")) > 0 {
			delete(target, elem.Field(i).Tag.Get("json"))
		}
	}

	err := service.ServiceUserInstance.UserUpdateForMap(target)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func DeleteUserList(c *gin.Context) {
	var request req.IdsReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	err := service.ServiceUserInstance.DeleteBannerList(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func GetUserList(c *gin.Context) {
	var request req.UserListReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, total, err := service.ServiceUserInstance.GetUserList(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"total":    total,
		"page":     request.Page,
		"pageSize": request.PageSize,
	})
}

func LoginHandler(c *gin.Context) {
	atom := sessionHandler.GetAtom(c)

	var captchaCheckReq CaptchaCheckReq
	if err := c.ShouldBindBodyWith(&captchaCheckReq, binding.JSON); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	cache, err := GetCaptchaCache()
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	key := c.ClientIP()
	if !CaptchaStore.Verify(captchaCheckReq.CaptchaId, captchaCheckReq.Captcha, true) {
		baseHttp.WriteResponse(c, http.StatusBadRequest, "验证码验证失败！", nil)
		return
	}

	var loginRequest req.LoginRequest
	err = c.ShouldBindBodyWith(&loginRequest, binding.JSON)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	user, err := store.GetUserStore().GetByName(loginRequest.Username)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	if user.Enable != 1 {
		baseHttp.WriteResponse(c, http.StatusBadRequest, errCode.UserStatusErr, nil)
		return
	}

	if err := baseAuth.Compare(user.Password, loginRequest.Password); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, errCode.PasswordErr, nil)
		return
	}

	response, err := remoteRpc.GetSessionRpc().SessionRpcServiceClient.SessionCreate(c, &sessionProto.SessionCreateRequest{
		Uid: user.Uid,
		Cv:  atom.CV,
	})

	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, errCode.SessionErr, nil)
		return
	}

	cache.Increment(key, 1)

	baseHttp.WriteResponse(c, 0, "login success", gin.H{
		"sid":  response.Sid,
		"user": user,
	})

}

func GetSmsCodeHandler(c *gin.Context) {
	var request req.SmsCodeRequest
	if err := c.ShouldBindBodyWith(&request, binding.JSON); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	response, err := remoteRpc.GetSmsRpc().SmsRpcServiceClient.SendSmsCode(c, &smsProto.SendSmsRequest{
		Phone: request.Phone,
	})
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	if response.Code != 0 {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, response.Msg, nil)
		return
	}

	baseHttp.WriteResponse(c, 0, "success", nil)
}

func PhoneLoginHandler(c *gin.Context) {
	var request req.PhoneLoginRequest
	if err := c.ShouldBindBodyWith(&request, binding.JSON); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	response1, err := remoteRpc.GetSmsRpc().SmsRpcServiceClient.CheckSmsCode(c, &smsProto.CheckSmsRequest{
		Phone:   request.Phone,
		SmsCode: request.SmsCode,
	})
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	if response1.Code != 0 {
		baseHttp.WriteResponse(c, http.StatusBadRequest, response1.Msg, nil)
		return
	}

	user, err := store.GetUserStore().GetByRegisterPhone(request.Phone)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	if user.Enable != 1 {
		baseHttp.WriteResponse(c, http.StatusBadRequest, errCode.UserStatusErr, nil)
		return
	}

	atom := sessionHandler.GetAtom(c)
	response, err := remoteRpc.GetSessionRpc().SessionRpcServiceClient.SessionCreate(c, &sessionProto.SessionCreateRequest{
		Uid: user.Uid,
		Cv:  atom.CV,
	})

	baseHttp.WriteResponse(c, 0, "login success", gin.H{
		"sid": response.Sid,
		"uid": user.Uid,
	})
}

func UserSelfGet(c *gin.Context) {
	uid := c.GetInt64(KEY_AUTH_UID)
	user, err := store.GetUserStore().GetByUid(uid)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", user)
}

func LoginUserInfo(c *gin.Context) {
	uid := c.GetInt64(KEY_AUTH_UID)
	user, err := store.GetUserStore().GetByUid(uid)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", user)
}
